package com.gitee.kamismile.stoneComEx.common.filter.servlet;

import com.gitee.kamismile.stone.commmon.util.JsonUtil;
import com.gitee.kamismile.stone.commmon.util.ValueUtils;
import com.gitee.kamismile.stone.commmon.vertx.engine.VertxMembershipListener;
import com.gitee.kamismile.stoneComEx.common.Constant;
import com.gitee.kamismile.stoneComEx.common.exception.servlet.ServletErrorEnum;
import com.gitee.kamismile.stoneComEx.util.IpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.WebUtils;

import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;

/**
 * Created by lidong on 15-11-18.
 */
public class LoggingInterceptor implements AsyncHandlerInterceptor {
    protected final Logger logger =  LoggerFactory.getLogger("bLog");
    private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime");

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Read inputStream from requestWrapper and log it
//        ContentCachingRequestWrapper class only supports the following:
//        Content-Type:application/x-www-form-urlencoded
//        Method-Type:POST
//        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
        long beginTime = System.currentTimeMillis();
        startTimeThreadLocal.set(beginTime);
//        responseWrapper.copyBodyToResponse();
        Enumeration<String> names = request.getHeaderNames();
        Map<String, String> nameMap = new HashMap<>();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String value = request.getHeader(name);
            nameMap.put(name, value);
        }
        logger.info(MessageFormat.format("请求接口:{0} {1} {2} 调用参数:{3} IP:{4} ",
                request.getMethod(),
                ValueUtils.isStringNull(request.getAttribute(ServletErrorEnum.URL.getTypeName()), request.getRequestURI()),
                JsonUtil.toJson(nameMap),
                JsonUtil.toJson(getRequestMap(request)), IpUtil.getIp(request)));

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        long beginTime = startTimeThreadLocal.get();
        long time = System.currentTimeMillis() - beginTime;
        Enumeration<String> names = request.getHeaderNames();
        Map<String, String> nameMap = new HashMap<>();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String value = request.getHeader(name);
            nameMap.put(name, value);
        }
        startTimeThreadLocal.remove();
        Map<String, String> requestMap = getRequestMap(request);
        if (time > Constant.DEFAULT_TIME_LOG || StringUtils.isNotBlank(requestMap.get("requestBody"))) {
            logger.info(MessageFormat.format("调用接口过程:{0} {1} {2} 调用参数:{3} 花费时间:{4} IP:{5}  ",
                    request.getMethod(),
                    ValueUtils.isStringNull(request.getAttribute(ServletErrorEnum.URL.getTypeName()), request.getRequestURI()),
                    JsonUtil.toJson(nameMap),
                    JsonUtil.toJson(requestMap), time, IpUtil.getIp(request)));
        }
    }

    private Map<String, String> getRequestMap(HttpServletRequest request) throws Exception {
        Object requestObj = request;
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, String> map = new HashMap<String, String>();
        Iterator<String> it = parameterMap.keySet().iterator();
        while (it.hasNext()) {
            String objs = (String) it.next();
            String[] obj = (String[]) parameterMap.get(objs);
            map.put(objs, StringUtils.join(obj, ","));
        }
//        ServletInputStream io = request.getInputStream();
//        map.put("requestBody",StreamUtils.copyToString(io, Charset.forName("UTF-8")));
//        byte[] buf = ((ContentCachingRequestWrapper) request).getContentAsByteArray();
//        map.put("requestBody",new String(buf, 0, buf.length, Charset.forName("UTF-8")));
        boolean isMultipart = MultipartResolutionDelegate.isMultipartRequest(request);
        if (!isMultipart) {
            String requestBody = "";
            ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
            if (Objects.nonNull(wrapper)) {
                requestBody = new String(wrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
            }
            map.put("requestBody", requestBody);
        }
        return map;
    }


}
